package com.kkelectronics.w2b.beangen.service.model;

import java.util.List;
import java.util.Set;

import com.kkelectronics.w2b.devplugin.codegenerator.core.databean.InterfaceGenerator;
import com.kkelectronics.w2b.devplugin.codegenerator.model.Field;

public enum BeanType {
	BEAN, INTERFACE, JS;

	public void populateImports(final BeanClass bean, final List<BeanField> fields) {
		switch (this) {
		case BEAN:
			populateBeanImports(bean, fields);
			break;
		case INTERFACE:
			populateInterfaceImports(bean, fields);
			break;
		case JS:
			populateJSImports(bean, fields);
			break;
		default:
			break;
		}
	}

	public String getClassHeader(BeanClass bean) {
		StringBuilder b = new StringBuilder();
		b.append("package ");
		b.append(bean.getPackageName());
		b.append(";");

		b.append(System.getProperty("line.separator"));
		b.append(System.getProperty("line.separator"));

		Set<String> imports = bean.getImports();

		for (String string : imports) {
			b.append("import ");
			b.append(string);
			b.append(";");
			b.append(System.getProperty("line.separator"));
		}
		b.append(System.getProperty("line.separator"));

		b.append("/**");

		b.append(System.getProperty("line.separator"));
		b.append(" * ");
		b.append(getClassComment(bean));

		b.append(System.getProperty("line.separator"));
		b.append(" */");

		b.append(System.getProperty("line.separator"));

		return b.toString();
	}

	public String getClassNameLine(final BeanClass bean) {
		String classComment = "";
		switch (this) {
		case BEAN:
			classComment = generateBeanName(bean);
			break;
		case INTERFACE:
			classComment = generateInterfaceName(bean);
			break;
		case JS:
			classComment = generateJSName(bean);
			break;
		default:
			break;
		}
		return classComment;
	}

	public String getClassContent(final BeanClass bean, final List<Field> fields) {
		String classContent = "";
		switch (this) {
		case BEAN:
//			classContent = generateBeanContent(bean, fields);
			break;
		case INTERFACE:
			classContent = generateInterfaceContent(bean, fields);
			break;
		case JS:
//			classContent = generateJSContent(bean, fields);
//			classContent.replaceAll("{", "/*- {");
//			classContent.replaceAll("}", "} -*/");
			break;
		default:
			break;
		}
		return classContent;
	}

	private void populateJSImports(final BeanClass bean, final List<BeanField> fields) {
		bean.addImport("com.google.gwt.core.client.JavaScriptObject");
		for (BeanField beanField : fields) {
			if (!beanField.isRawType() && beanField.getTypeName().contains("List")) {
				bean.addImport("com.google.gwt.core.client.JsArray");
			}
		}
	}

	private void populateInterfaceImports(final BeanClass bean, final List<BeanField> fields) {
		for (BeanField beanField : fields) {
			if (!beanField.isRawType())
				bean.addImport("com.kk_electronic.w2b.legacy.datajs.interfaces.I" + beanField.getTypeShortName().replace("JS", ""));
		}
	}

	private void populateBeanImports(final BeanClass bean, final List<BeanField> fields) {
		bean.addImport("com.kk_electronic.w2b.legacy.datajs.interfaces.IBusinessObject");
		bean.addImport("com.kk_electronic.w2b.legacy.datajs.interfaces.I" + bean.getClassName().replace("Bean", ""));
		bean.addImport("com.kk_electronic.w2b.legacy.datajs.js." + bean.getClassName().replace("Bean", "JS"));
		for (BeanField beanField : fields) {
			if (!beanField.isRawType())
				bean.addImport("com.kk_electronic.w2b.legacy.datajs.interfaces.I" + beanField.getTypeShortName().replace("JS", ""));
		}
	}

	private String getClassComment(final BeanClass bean) {
		String classComment = "";
		switch (this) {
		case BEAN:
			classComment = generateBeanComment(bean);
			break;
		case INTERFACE:
			classComment = generateInterfaceComment(bean);
			break;
		case JS:
			classComment = generateJSComment(bean);
			break;
		default:
			break;
		}
		return classComment;
	}

	private String generateJSComment(final BeanClass bean) {
		return bean.getClassComment();
	}

	private String generateInterfaceComment(final BeanClass bean) {
		return bean.getClassComment();
	}

	private String generateBeanComment(final BeanClass bean) {
		return bean.getClassComment();
	}

	private String generateJSName(final BeanClass bean) {
		final StringBuilder b = new StringBuilder();
		b.append("public class ");
		b.append(bean.getClassName());
		b.append(" extends JavaScriptObject {");
		b.append(System.getProperty("line.separator"));
		return b.toString();
	}

	private String generateInterfaceName(final BeanClass bean) {
		final StringBuilder b = new StringBuilder();
		b.append("public interface ");
		b.append(bean.getClassName());
		b.append(" {");
		b.append(System.getProperty("line.separator"));
		return b.toString();
	}

	private String generateBeanName(final BeanClass bean) {
		final StringBuilder b = new StringBuilder();
		b.append("public class ");
		b.append(bean.getClassName());
		b.append(" implements I");
		b.append(bean.getClassName().replace("Bean", ""));
		b.append(", IBusinessObject<");
		b.append(bean.getClassName().replace("Bean", "JS"));
		b.append(">");
		b.append(" {");
		b.append(System.getProperty("line.separator"));
		return b.toString();
	}

	/**
	 * @param bean
	 * @param fields
	 * @return
	 */
	private String generateJSContent(final BeanClass bean, final List<BeanField> fields) {
		final StringBuilder b = new StringBuilder();

		b.append(System.getProperty("line.separator"));

		b.append("\tprotected ");
		b.append(bean.getClassName());
		b.append("() {");
		b.append(System.getProperty("line.separator"));

		addStatement("\t\tsuper();", b);

		addStatement("\t}", b);

		b.append(System.getProperty("line.separator"));

		b.append("\tpublic static final native ");
		b.append(bean.getClassName());
		b.append(" create(JavaScriptObject obj) /*-{");
		b.append(System.getProperty("line.separator"));

		addStatement("\t\treturn obj", b);

		addStatement("\t}-*/;", b);

		for (BeanField field : fields) {
			// get
			b.append(System.getProperty("line.separator"));

			addStatement("\t/**", b);

			if (field.getTypeShortName().contains("List")) {
				b.append("\t * @return {@link JsArray} of {@link ");
				b.append(field.getTypeShortName().substring(field.getTypeShortName().indexOf("<"), field.getTypeShortName().indexOf(">")) + "JS");
				b.append("} - ");
			} else {
				b.append("\t * @return {@link ");
				b.append(field.getTypeShortName());
				b.append("} - ");
			}
			b.append(field.getComment());
			b.append(System.getProperty("line.separator"));
			addStatement("\t */", b);

			b.append("\tpublic final native ");
			if (field.getTypeShortName().contains("List"))
				b.append(field.getTypeShortName().replace("List", "JsArray").replace(">", "JS>"));
			else
				b.append(field.getTypeShortName());
			b.append(" get");
			b.append(field.getName());
			b.append("() /*-{");
			b.append(System.getProperty("line.separator"));

			b.append("\t\treturn this.");
			b.append(field.getName());
			b.append(";");
			b.append(System.getProperty("line.separator"));

			addStatement("\t}-*/;", b);

			// set
			b.append(System.getProperty("line.separator"));

			addStatement("\t/**", b);
			if (field.getTypeShortName().contains("List")) {
				b.append("\t * @param {@link JsArray} of {@link ");
				b.append(field.getTypeShortName().substring(field.getTypeShortName().indexOf("<"), field.getTypeShortName().indexOf(">")) + "JS");
				b.append("} value - ");
			} else {
				b.append("\t * @param {@link ");
				b.append(field.getTypeShortName());
				b.append("} value - ");
			}
			b.append(field.getComment());
			b.append(System.getProperty("line.separator"));
			addStatement("\t */", b);

			b.append("\tpublic final native void ");
			b.append("set");
			b.append(field.getName());
			b.append("(");
			if (field.getTypeShortName().contains("List")) {
				b.append("final JavaScriptObject value");
			} else {
				b.append("final ");
				b.append(field.getTypeShortName());
				b.append(" value");
			}
			b.append(") /*-{");
			b.append(System.getProperty("line.separator"));

			b.append("\t\tthis.");
			b.append(field.getName());
			b.append(" = value;");
			b.append(System.getProperty("line.separator"));

			addStatement("\t}-*/;", b);
		}

		return b.toString();
	}

	/**
	 * @param useInToString
	 */
	private String generateInterfaceContent(final BeanClass bean, final List<Field> fields) {
		
		InterfaceGenerator igen = new InterfaceGenerator();
		return igen.gen(bean, fields).toString();
//		final StringBuilder b = new StringBuilder();
//
//		for (BeanField field : fields) {
//			// get
//			b.append(System.getProperty("line.separator"));
//
//			addStatement("\t/**", b);
//
//			if (field.getTypeShortName().contains("List")) {
//				b.append("\t * @return {@link List} of {@link ");
//				b.append("I" + field.getTypeShortName().substring(field.getTypeShortName().indexOf("<") + 1, field.getTypeShortName().indexOf(">")));
//				b.append("} - ");
//			} else if (field.isRawType()) {
//				b.append("\t * @return {@link ");
//				b.append(field.getTypeShortName());
//				b.append("} - ");
//			} else {
//				b.append("\t * @return {@link ");
//				b.append("I" + field.getTypeShortName().replace("JS", ""));
//				b.append("} - ");
//			}
//			b.append(field.getComment());
//			b.append(System.getProperty("line.separator"));
//			addStatement("\t */", b);
//
//			b.append("\t");
//			if (field.getTypeShortName().contains("List"))
//				b.append(field.getTypeShortName().replace("<", "<I"));
//			else if (field.isRawType())
//				b.append(field.getTypeShortName());
//			else
//				b.append("I" + field.getTypeShortName().replace("JS", ""));
//			b.append(" get");
//			b.append(field.getName());
//			b.append("();");
//
//			// set
//			b.append(System.getProperty("line.separator"));
//			b.append(System.getProperty("line.separator"));
//
//			addStatement("\t/**", b);
//			if (field.getTypeShortName().contains("List")) {
//				b.append("\t * @param {@link List} of {@link ");
//				b.append("I" + field.getTypeShortName().substring(field.getTypeShortName().indexOf("<") + 1, field.getTypeShortName().indexOf(">")));
//				b.append("} value - ");
//			} else if (field.isRawType()) {
//				b.append("\t * @param {@link ");
//				b.append(field.getTypeShortName());
//				b.append("} value - ");
//			} else {
//				b.append("\t * @param {@link IBusinessObject} value - ");
//			}
//			b.append(field.getComment());
//			b.append(System.getProperty("line.separator"));
//			addStatement("\t */", b);
//
//			b.append("\tvoid ");
//			b.append("set");
//			b.append(field.getName());
//			b.append("(");
//			if (field.getTypeShortName().contains("List")) {
//				b.append("final ");
//				b.append(field.getTypeShortName().replace("<", "<I"));
//				b.append(" value");
//			} else if (field.isRawType()) {
//				b.append("final ");
//				b.append(field.getTypeShortName());
//				b.append(" value");
//			} else {
//				b.append("final IBusinessObject<?> value");
//			}
//			b.append(");");
//			b.append(System.getProperty("line.separator"));
//		}
//
//		return b.toString();
	}

	private String generateBeanContent(final BeanClass bean, final List<BeanField> fields) {
		final StringBuilder b = new StringBuilder();
		String jsBean = bean.getClassName().replace("Bean", "JS");

		b.append(System.getProperty("line.separator"));

		b.append("\tprivate ");
		b.append(jsBean);
		b.append(" jsObject;");
		b.append(System.getProperty("line.separator"));
		b.append(System.getProperty("line.separator"));

		b.append("\tpublic ");
		b.append(bean.getClassName());
		b.append("() {");
		b.append(System.getProperty("line.separator"));
		addStatement("\t}", b);
		b.append(System.getProperty("line.separator"));

		b.append("\tpublic ");
		b.append(bean.getClassName());
		b.append("(");
		b.append(jsBean);
		b.append(" js) {");
		b.append(System.getProperty("line.separator"));
		addStatement("\t\tsetJS(js);", b);
		addStatement("\t}", b);

		for (BeanField field : fields) {

			// get
			b.append(System.getProperty("line.separator"));

			addStatement("\t/**", b);

			if (field.getTypeShortName().contains("List")) {
				String shortType = field.getTypeShortName().substring(field.getTypeShortName().indexOf("<") + 1, field.getTypeShortName().indexOf(">"));
				b.append("\t * @return {@link List} of {@link I");
				b.append(shortType);
				b.append("} - ");
			} else {
				b.append("\t * @return {@link ");
				b.append(field.getTypeShortName());
				b.append("} - ");
			}
			b.append(field.getComment());
			b.append(System.getProperty("line.separator"));
			addStatement("\t */", b);

			addStatement("\t@Override  ", b);
			b.append("\tpublic ");
			if (field.getTypeShortName().contains("List"))
				b.append(field.getTypeShortName().replace("<", "<I"));
			else if (field.isRawType())
				b.append(field.getTypeShortName());
			else
				b.append("I" + field.getTypeShortName().replace("JS", ""));
			b.append(" get");
			b.append(field.getName());
			b.append("() {");
			b.append(System.getProperty("line.separator"));

			if (field.getTypeShortName().contains("List")) {
				String shortType = field.getTypeShortName().substring(field.getTypeShortName().indexOf("<") + 1, field.getTypeShortName().indexOf(">"));
				b.append("\t\treturn new JSBasedArrayList<");
				b.append(shortType);
				b.append("JS, I");
				b.append(shortType);
				b.append(">(jsObject.get");
				b.append(field.getName());
				b.append(", I");
				b.append(shortType);
				b.append(".class);");
				b.append(System.getProperty("line.separator"));
			} else if (field.isRawType()){
				b.append("\t\treturn jsObject.get");
				b.append(field.getName());
				b.append("();");
				b.append(System.getProperty("line.separator"));
			} else {
				b.append("\t\treturn BOFactory.getInstance().createBO(");
				b.append("I" + field.getTypeShortName().replace("JS", ""));
				b.append(".class, jsObject.get");
				b.append(field.getName());
				b.append("());");
				b.append(System.getProperty("line.separator"));
			}
			
			// BOFactory.getInstance().createBO(AlarmLogInfo.class, js)

			addStatement("\t};", b);

			// set
			b.append(System.getProperty("line.separator"));

			addStatement("\t/**", b);
			if (field.getTypeShortName().contains("List")) {
				b.append("\t * @param {@link List} of {@link I");
				b.append(field.getTypeShortName().substring(field.getTypeShortName().indexOf("<") + 1, field.getTypeShortName().indexOf(">")));
				b.append("} value - ");
			} else {
				b.append("\t * @param {@link ");
				b.append(field.getTypeShortName());
				b.append("} value - ");
			}
			b.append(field.getComment());
			b.append(System.getProperty("line.separator"));
			addStatement("\t */", b);

			addStatement("\t@Override  ", b);
			b.append("\tpublic void ");
			b.append("set");
			b.append(field.getName());
			b.append("(");
			if (field.getTypeShortName().contains("List")) {
				String shortType = field.getTypeShortName().substring(field.getTypeShortName().indexOf("<") + 1, field.getTypeShortName().indexOf(">"));
				b.append("final List<I");
				b.append(shortType);
				b.append("> value) {");
				b.append(System.getProperty("line.separator"));
				b.append("\t\tjsObject.set");
				b.append(field.getName());
				b.append("(((JSBasedArrayList)value).getJSArray());");
				b.append(System.getProperty("line.separator"));
			} else if (field.isRawType()) {
				b.append("final ");
				b.append(field.getTypeShortName());
				b.append(" value) {");
				b.append(System.getProperty("line.separator"));

				b.append("\t\tjsObject.set");
				b.append(field.getName());
				b.append("(value);");
				b.append(System.getProperty("line.separator"));
			} else {
				b.append("final IBusinessObject<");
				b.append(field.getTypeShortName());
				b.append("> value) {");
				b.append(System.getProperty("line.separator"));

				b.append("\t\tjsObject.set");
				b.append(field.getName());
				b.append("(value.getJS());");
				b.append(System.getProperty("line.separator"));
			}

			addStatement("\t}", b);
		}

		b.append(System.getProperty("line.separator"));
		addStatement("\t@Override  ", b);
		b.append("\tpublic void setJS(");
		b.append(jsBean);
		b.append(" js) {");
		b.append(System.getProperty("line.separator"));
		addStatement("\t\tjsObject = js;", b);
		addStatement("\t}", b);
		b.append(System.getProperty("line.separator"));

		addStatement("\t@Override  ", b);
		b.append("\tpublic ");
		b.append(jsBean);
		b.append(" getJS() {");
		b.append(System.getProperty("line.separator"));
		addStatement("\t\treturn jsObject;", b);
		addStatement("\t}", b);
		b.append(System.getProperty("line.separator"));

		return b.toString();
	}

	private void addStatement(String str, StringBuilder b) {
		b.append(str);
		b.append(System.getProperty("line.separator"));
	}

}
